﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ashlen.Portal.Core;
using Ashlen.Portal.Core.DataInterfaces;
using Ashlen.Portal.Data.SqlServer;
using FeedDotNet.Common;
using System.Configuration;

namespace Ashlen.Utility.NewsService
{
    /// <summary>
    /// This class encapsulates the retrieval of news feeds.
    /// </summary>
    /// <remarks>
    /// Author: Shailen Sukul
    /// Date: 08 Oct 2008
    /// </remarks>
    public sealed class RSSHelper
    {
        /// <summary>
        /// Crawl feeds will accept a sourceId, lookup rss values for 
        /// that source from the NewsSourceSection table and crawl the 
        /// feeds and populate the NewsFeed table.
        /// </summary>
        /// <param name="sourceId"></param>
        public void CrawlFeeds(int sourceId) {
            
            #region Variables
            int daysToKeep = 7;
            INewsDao dao = new NewsDao();
            IUtilityDao _util = UtilityDao.Instance;
            NewsFeed newsFeed = null;
            NewsSection newsSection = null;
            List<NewsFeed> feedsList = null;
            string feedWhereClause = string.Empty;
            string newsFeedGuid = string.Empty;
            bool isNew = false;
            Feed feed;
            #endregion

            #region Load Delete Interval from Config
            /* Get the number of days to keep the newsfeed for */
            try {
                daysToKeep = Convert.ToInt32(ConfigurationManager.AppSettings["DaysToKeep"]);
            }
            catch { daysToKeep = 7; }
            #endregion

            /* Load all sections in a source collection */
            NewsSource oSource = dao.GetNewsSource(sourceId) as NewsSource;
            /* Go thru sesction collection in the source */
            foreach (NewsSourceSection section in oSource.NewsSourceSection) {
                try {
                    /* Get the section */
                    newsSection = dao.GetNewsSection(section.SectionId) as NewsSection;
                    /* Get a list of feeds using the FeedDotNet API */
                    feed = FeedDotNet.FeedReader.Read(section.RSSUri);

                    /* Go thru feed collection */
                    foreach (FeedItem item in feed.Items) {
                        /* Find if the feed exists by looking up the guid for the source 
                        * Some crappy feeds like FijiLive do not have a guid. */
                        newsFeedGuid = (item.Guid != null ? item.Guid.Id : item.WebUris[0].Uri);

                        /* Check if the feed already exists (based on source and guid). */
                        newsFeed = dao.GetNewsFeed(newsFeedGuid, section.SourceId) as NewsFeed;
                        isNew = (newsFeed == null);
                        if (isNew) { newsFeed = new NewsFeed(); }

                        if (isNew || !item.Updated.HasValue || newsFeed.DateUpdated.Value.ToUniversalTime() < item.Updated.Value ||
                            !item.Published.HasValue || newsFeed.DateUpdated.Value.ToUniversalTime() < item.Published.Value) {

                            newsFeed.Caption = item.Title;
                            newsFeed.FullText = item.ContentOrSummary;
                            newsFeed.Guid = newsFeedGuid;
                            newsFeed.Uri = item.WebUris[0].Uri;
                            /* If the feed specified an updated date, the use it. */
                            if (item.Updated.HasValue) {
                                newsFeed.DateUpdated = item.Updated.Value.ToUniversalTime();
                            }
                            /* If the feed specified a published date, then use it. */
                            if (item.Published.HasValue) {
                                newsFeed.DateCreated = item.Published.Value.ToUniversalTime();
                                if (!item.Updated.HasValue) { newsFeed.DateUpdated = item.Published.Value.ToUniversalTime(); }
                            }
                            /* If BOTH the published date and updated date are not supplied, then use the current datetime. */
                            if (!item.Published.HasValue && !item.Updated.HasValue) {
                                newsFeed.DateUpdated = DateTime.Now.ToUniversalTime();
                            }
                            /* If the published date is not supplied, then use the current datetime. */
                            if (!item.Published.HasValue) { newsFeed.DateCreated = DateTime.Now.ToUniversalTime(); }
                            newsFeed.UserUpdated = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                            if (isNew) { newsFeed.UserCreated = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                            }
                            newsFeed.NewsSource = oSource;
                            
                            /* Save the news feed*/
                            dao.SaveFeed(newsFeed, newsSection);                            
                        }
                    }
                    /* -- End feed collection -- */
                }
                /* TODO: Catch Connection pool exception, wait for a random value of 2-3 minutes and then
                 try again. This may be caused by different service threads being run simaltaneously and 
                 using up all the connection pool. */
                catch (Exception ex) { throw ex; }
            }
            /* -- End source collection -- */

            /* Delete feeds older than 7 days. */
            try {
                dao.DeleteOldFeeds(daysToKeep);
            }
            catch { }
        }
    }
}
